use crate::loader::{RulesLoader, RulesLoaderExt};
use mf_state::resource::Resource;
use std::{ops::Deref, sync::Arc};
use zen_engine::DecisionEngine;

/// 规则引擎，基于zen-engine实现
///
/// 规则引擎负责执行业务规则，处理计价逻辑，是系统核心的计算组件。
/// 它封装了底层的决策引擎，提供了便捷的规则执行接口。
///
/// # 功能概述
/// - 管理和执行计价业务规则
/// - 支持规则的加载、解析和评估
/// - 通过决策引擎实现复杂的计价逻辑
/// - 提供统一的规则执行接口，简化上层组件的使用
///
/// # 架构设计
/// 规则引擎采用了分层设计：
/// - 最上层是 RulesEngine，提供对外接口
/// - 中间层是 DecisionEngine，处理规则执行逻辑
/// - 底层是 RulesLoader，负责规则加载和管理
///
/// # 使用示例
/// ```
/// let loader = Arc::new(MyRulesLoader::new());
/// let rules_engine = RulesEngine::new(loader);
///
/// // 可直接调用底层决策引擎的方法
/// let result = rules_engine.evaluate(context).await?;
/// ```
#[derive(Debug, Clone)]
pub struct RulesEngine {
    /// 决策引擎实例，使用Arc包装以支持共享和并发访问
    ///
    /// 泛型参数指定了使用的规则加载器和自定义节点处理器类型：
    /// - RulesLoader: 负责加载和管理规则定义
    /// - NoopCustomNode: 无操作的自定义节点适配器，用于扩展节点类型
    ///
    /// 决策引擎是规则执行的核心，处理规则的评估和结果计算
    pub decision_engine: Arc<DecisionEngine>,
}

impl Resource for RulesEngine {}

impl RulesEngine {
    /// 创建新的规则引擎实例
    ///
    /// 该方法初始化规则引擎，设置规则加载器，并配置底层决策引擎
    ///
    /// # 参数
    /// * `loader` - 规则加载器，负责加载和提供规则定义
    ///   实现了 RulesLoaderExt trait 的组件可以作为规则源
    ///
    /// # 返回
    /// * `Self` - 规则引擎实例，已配置完成并可立即使用
    ///
    /// # 内部实现
    /// 1. 创建 RulesLoader 实例，封装外部提供的加载器
    /// 2. 创建默认的决策引擎，并设置规则加载器
    /// 3. 将决策引擎封装为 Arc 智能指针，支持共享访问
    pub fn new(loader: Arc<dyn RulesLoaderExt>) -> Self {
        // 创建一个新的规则加载器实例
        // RulesLoader 是对外部加载器的适配器，转换为决策引擎需要的格式
        let loader = RulesLoader::new(loader);

        // 创建并初始化默认的决策引擎，并设置规则加载器
        // with_loader 方法配置决策引擎使用的规则源
        Self { decision_engine: Arc::new(DecisionEngine::default().with_loader(Arc::new(loader))) }
    }
}

/// 实现 Deref trait，允许 RulesEngine 透明地解引用为底层的 DecisionEngine
///
/// 这样可以直接在 RulesEngine 实例上调用 DecisionEngine 的方法，
/// 无需显式访问内部的 decision_engine 字段
///
/// # 优势
/// - 简化了 API 接口，减少了冗余代码
/// - 保持了类型安全性，同时提供了便捷的访问方式
/// - 使上层代码可以无缝使用底层引擎的全部功能
///
/// # 使用示例
/// ```
/// // 无需通过 decision_engine 字段访问
/// let result = rules_engine.evaluate(context).await?;
///
/// // 等同于
/// let result = rules_engine.decision_engine.evaluate(context).await?;
/// ```
impl Deref for RulesEngine {
    type Target = DecisionEngine;

    fn deref(&self) -> &Self::Target {
        &self.decision_engine
    }
}
